package org.fisco.bcos.sdk.demo.contract;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.v3.client.Client;
import org.fisco.bcos.sdk.v3.codec.datatypes.Function;
import org.fisco.bcos.sdk.v3.codec.datatypes.Type;
import org.fisco.bcos.sdk.v3.codec.datatypes.TypeReference;
import org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple10;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.v3.contract.Contract;
import org.fisco.bcos.sdk.v3.crypto.CryptoSuite;
import org.fisco.bcos.sdk.v3.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.v3.model.CryptoType;
import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class MultiMapTest extends Contract {
    public static final String[] BINARY_ARRAY = {
        "608060405234801561001057600080fd5b50610bf1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063693ec85e1461003b578063e942b5161461006d575b600080fd5b61004e61004936600461098c565b610082565b6040516100649a99989796959493929190610a25565b60405180910390f35b61008061007b366004610b00565b6106c8565b005b6060806060806060806060806060806000808c6040516100a29190610b64565b9081526020016040518091039020604051806101400160405290816000820180546100cc90610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546100f890610b80565b80156101455780601f1061011a57610100808354040283529160200191610145565b820191906000526020600020905b81548152906001019060200180831161012857829003601f168201915b5050505050815260200160018201805461015e90610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461018a90610b80565b80156101d75780601f106101ac576101008083540402835291602001916101d7565b820191906000526020600020905b8154815290600101906020018083116101ba57829003601f168201915b505050505081526020016002820180546101f090610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461021c90610b80565b80156102695780601f1061023e57610100808354040283529160200191610269565b820191906000526020600020905b81548152906001019060200180831161024c57829003601f168201915b5050505050815260200160038201805461028290610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546102ae90610b80565b80156102fb5780601f106102d0576101008083540402835291602001916102fb565b820191906000526020600020905b8154815290600101906020018083116102de57829003601f168201915b5050505050815260200160048201805461031490610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461034090610b80565b801561038d5780601f106103625761010080835404028352916020019161038d565b820191906000526020600020905b81548152906001019060200180831161037057829003601f168201915b505050505081526020016005820180546103a690610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546103d290610b80565b801561041f5780601f106103f45761010080835404028352916020019161041f565b820191906000526020600020905b81548152906001019060200180831161040257829003601f168201915b5050505050815260200160068201805461043890610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461046490610b80565b80156104b15780601f10610486576101008083540402835291602001916104b1565b820191906000526020600020905b81548152906001019060200180831161049457829003601f168201915b505050505081526020016007820180546104ca90610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546104f690610b80565b80156105435780601f1061051857610100808354040283529160200191610543565b820191906000526020600020905b81548152906001019060200180831161052657829003601f168201915b5050505050815260200160088201805461055c90610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461058890610b80565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b505050505081526020016009820180546105ee90610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461061a90610b80565b80156106675780601f1061063c57610100808354040283529160200191610667565b820191906000526020600020905b81548152906001019060200180831161064a57829003601f168201915b5050505050815250509050806000015181602001518260400151836060015184608001518560a001518660c001518760e001518861010001518961012001519a509a509a509a509a509a509a509a509a509a50509193959799509193959799565b6000604051806101400160405280838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152509050806000846040516107239190610b64565b9081526020016040518091039020600082015181600001908051906020019061074d929190610850565b5060208281015180516107669260018501920190610850565b5060408201518051610782916002840191602090910190610850565b506060820151805161079e916003840191602090910190610850565b50608082015180516107ba916004840191602090910190610850565b5060a082015180516107d6916005840191602090910190610850565b5060c082015180516107f2916006840191602090910190610850565b5060e0820151805161080e916007840191602090910190610850565b50610100820151805161082b916008840191602090910190610850565b506101208201518051610848916009840191602090910190610850565b505050505050565b82805461085c90610b80565b90600052602060002090601f01602090048101928261087e57600085556108c4565b82601f1061089757805160ff19168380011785556108c4565b828001600101855582156108c4579182015b828111156108c45782518255916020019190600101906108a9565b506108d09291506108d4565b5090565b5b808211156108d057600081556001016108d5565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261091057600080fd5b813567ffffffffffffffff8082111561092b5761092b6108e9565b604051601f8301601f19908116603f01168101908282118183101715610953576109536108e9565b8160405283815286602085880101111561096c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561099e57600080fd5b813567ffffffffffffffff8111156109b557600080fd5b6109c1848285016108ff565b949350505050565b60005b838110156109e45781810151838201526020016109cc565b838111156109f3576000848401525b50505050565b60008151808452610a118160208601602086016109c9565b601f01601f19169290920160200192915050565b6000610140808352610a398184018e6109f9565b90508281036020840152610a4d818d6109f9565b90508281036040840152610a61818c6109f9565b90508281036060840152610a75818b6109f9565b90508281036080840152610a89818a6109f9565b905082810360a0840152610a9d81896109f9565b905082810360c0840152610ab181886109f9565b905082810360e0840152610ac581876109f9565b9050828103610100840152610ada81866109f9565b9050828103610120840152610aef81856109f9565b9d9c50505050505050505050505050565b60008060408385031215610b1357600080fd5b823567ffffffffffffffff80821115610b2b57600080fd5b610b37868387016108ff565b93506020850135915080821115610b4d57600080fd5b50610b5a858286016108ff565b9150509250929050565b60008251610b768184602087016109c9565b9190910192915050565b600181811c90821680610b9457607f821691505b60208210811415610bb557634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220e93d39037bc817daea3e853c096015de534f82d077bc4ab92750376a62ac573864736f6c634300080b0033"
    };

    public static final String BINARY =
            org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {
        "608060405234801561001057600080fd5b50610bf1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631a391cb41461003b5780637b1b8e0314610050575b600080fd5b61004e61004936600461098c565b610082565b005b61006361005e3660046109f0565b61020a565b6040516100799a99989796959493929190610a89565b60405180910390f35b6000604051806101400160405280838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152602001838152509050806000846040516100dd9190610b64565b90815260200160405180910390206000820151816000019080519060200190610107929190610850565b5060208281015180516101209260018501920190610850565b506040820151805161013c916002840191602090910190610850565b5060608201518051610158916003840191602090910190610850565b5060808201518051610174916004840191602090910190610850565b5060a08201518051610190916005840191602090910190610850565b5060c082015180516101ac916006840191602090910190610850565b5060e082015180516101c8916007840191602090910190610850565b5061010082015180516101e5916008840191602090910190610850565b506101208201518051610202916009840191602090910190610850565b505050505050565b6060806060806060806060806060806000808c60405161022a9190610b64565b90815260200160405180910390206040518061014001604052908160008201805461025490610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461028090610b80565b80156102cd5780601f106102a2576101008083540402835291602001916102cd565b820191906000526020600020905b8154815290600101906020018083116102b057829003601f168201915b505050505081526020016001820180546102e690610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461031290610b80565b801561035f5780601f106103345761010080835404028352916020019161035f565b820191906000526020600020905b81548152906001019060200180831161034257829003601f168201915b5050505050815260200160028201805461037890610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546103a490610b80565b80156103f15780601f106103c6576101008083540402835291602001916103f1565b820191906000526020600020905b8154815290600101906020018083116103d457829003601f168201915b5050505050815260200160038201805461040a90610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461043690610b80565b80156104835780601f1061045857610100808354040283529160200191610483565b820191906000526020600020905b81548152906001019060200180831161046657829003601f168201915b5050505050815260200160048201805461049c90610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546104c890610b80565b80156105155780601f106104ea57610100808354040283529160200191610515565b820191906000526020600020905b8154815290600101906020018083116104f857829003601f168201915b5050505050815260200160058201805461052e90610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461055a90610b80565b80156105a75780601f1061057c576101008083540402835291602001916105a7565b820191906000526020600020905b81548152906001019060200180831161058a57829003601f168201915b505050505081526020016006820180546105c090610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546105ec90610b80565b80156106395780601f1061060e57610100808354040283529160200191610639565b820191906000526020600020905b81548152906001019060200180831161061c57829003601f168201915b5050505050815260200160078201805461065290610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461067e90610b80565b80156106cb5780601f106106a0576101008083540402835291602001916106cb565b820191906000526020600020905b8154815290600101906020018083116106ae57829003601f168201915b505050505081526020016008820180546106e490610b80565b80601f016020809104026020016040519081016040528092919081815260200182805461071090610b80565b801561075d5780601f106107325761010080835404028352916020019161075d565b820191906000526020600020905b81548152906001019060200180831161074057829003601f168201915b5050505050815260200160098201805461077690610b80565b80601f01602080910402602001604051908101604052809291908181526020018280546107a290610b80565b80156107ef5780601f106107c4576101008083540402835291602001916107ef565b820191906000526020600020905b8154815290600101906020018083116107d257829003601f168201915b5050505050815250509050806000015181602001518260400151836060015184608001518560a001518660c001518760e001518861010001518961012001519a509a509a509a509a509a509a509a509a509a50509193959799509193959799565b82805461085c90610b80565b90600052602060002090601f01602090048101928261087e57600085556108c4565b82601f1061089757805160ff19168380011785556108c4565b828001600101855582156108c4579182015b828111156108c45782518255916020019190600101906108a9565b506108d09291506108d4565b5090565b5b808211156108d057600081556001016108d5565b63b95aa35560e01b600052604160045260246000fd5b600082601f83011261091057600080fd5b813567ffffffffffffffff8082111561092b5761092b6108e9565b604051601f8301601f19908116603f01168101908282118183101715610953576109536108e9565b8160405283815286602085880101111561096c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561099f57600080fd5b823567ffffffffffffffff808211156109b757600080fd5b6109c3868387016108ff565b935060208501359150808211156109d957600080fd5b506109e6858286016108ff565b9150509250929050565b600060208284031215610a0257600080fd5b813567ffffffffffffffff811115610a1957600080fd5b610a25848285016108ff565b949350505050565b60005b83811015610a48578181015183820152602001610a30565b83811115610a57576000848401525b50505050565b60008151808452610a75816020860160208601610a2d565b601f01601f19169290920160200192915050565b6000610140808352610a9d8184018e610a5d565b90508281036020840152610ab1818d610a5d565b90508281036040840152610ac5818c610a5d565b90508281036060840152610ad9818b610a5d565b90508281036080840152610aed818a610a5d565b905082810360a0840152610b018189610a5d565b905082810360c0840152610b158188610a5d565b905082810360e0840152610b298187610a5d565b9050828103610100840152610b3e8186610a5d565b9050828103610120840152610b538185610a5d565b9d9c50505050505050505050505050565b60008251610b76818460208701610a2d565b9190910192915050565b600181811c90821680610b9457607f821691505b60208210811415610bb55763b95aa35560e01b600052602260045260246000fd5b5091905056fea2646970667358221220b1ecefebd910c4858f29d61d4f1248bbb7e4c6949b955dc231b627d5fc529ba664736f6c634300080b0033"
    };

    public static final String SM_BINARY =
            org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {
        "[{\"conflictFields\":[{\"kind\":3,\"slot\":0,\"value\":[0]}],\"inputs\":[{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"selector\":[1765722206,2065403395],\"stateMutability\":\"view\",\"type\":\"function\"},{\"conflictFields\":[{\"kind\":3,\"slot\":0,\"value\":[0]}],\"inputs\":[{\"internalType\":\"string\",\"name\":\"k\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"v\",\"type\":\"string\"}],\"name\":\"set\",\"outputs\":[],\"selector\":[3913463062,439950516],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
    };

    public static final String ABI = org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_GET = "get";

    public static final String FUNC_SET = "set";

    protected MultiMapTest(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public static String getABI() {
        return ABI;
    }

    public Tuple10<String, String, String, String, String, String, String, String, String, String>
            get(String key) throws ContractException {
        final Function function =
                new Function(
                        FUNC_GET,
                        Arrays.<Type>asList(new Utf8String(key)),
                        Arrays.<TypeReference<?>>asList(
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {}));
        List<Type> results = executeCallWithMultipleValueReturn(function);
        return new Tuple10<
                String, String, String, String, String, String, String, String, String, String>(
                (String) results.get(0).getValue(),
                (String) results.get(1).getValue(),
                (String) results.get(2).getValue(),
                (String) results.get(3).getValue(),
                (String) results.get(4).getValue(),
                (String) results.get(5).getValue(),
                (String) results.get(6).getValue(),
                (String) results.get(7).getValue(),
                (String) results.get(8).getValue(),
                (String) results.get(9).getValue());
    }

    public TransactionReceipt set(String k, String v) {
        final Function function =
                new Function(
                        FUNC_SET,
                        Arrays.<Type>asList(new Utf8String(k), new Utf8String(v)),
                        Collections.<TypeReference<?>>emptyList(),
                        4);
        return executeTransaction(function);
    }

    public String set(String k, String v, TransactionCallback callback) {
        final Function function =
                new Function(
                        FUNC_SET,
                        Arrays.<Type>asList(new Utf8String(k), new Utf8String(v)),
                        Collections.<TypeReference<?>>emptyList(),
                        4);
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSet(String k, String v) {
        final Function function =
                new Function(
                        FUNC_SET,
                        Arrays.<Type>asList(new Utf8String(k), new Utf8String(v)),
                        Collections.<TypeReference<?>>emptyList(),
                        4);
        return createSignedTransaction(function);
    }

    public Tuple2<String, String> getSetInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function =
                new Function(
                        FUNC_SET,
                        Arrays.<Type>asList(),
                        Arrays.<TypeReference<?>>asList(
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {}));
        List<Type> results =
                this.functionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, String>(
                (String) results.get(0).getValue(), (String) results.get(1).getValue());
    }

    public static MultiMapTest load(
            String contractAddress, Client client, CryptoKeyPair credential) {
        return new MultiMapTest(contractAddress, client, credential);
    }

    public static MultiMapTest deploy(Client client, CryptoKeyPair credential)
            throws ContractException {
        return deploy(
                MultiMapTest.class,
                client,
                credential,
                getBinary(client.getCryptoSuite()),
                getABI(),
                null,
                null);
    }
}
